﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Net;
using System.IO;
using System.Text;
using System.Data;
using System.Collections;
using DBMethodsNamespace;
using VariablesGlobalesNamespace;
using BackstageMusiciansFriend;
using ControlLogNamespace;
using ControlTareaPendienteNamespace;
using System.Threading;
using ControlSesionNamespace;

namespace ControlCompetenciaNamespace
{

    public class CompetidorException : Exception
    {
        public CompetidorException(string strMessage)
            : base(strMessage)
        {

        }
    }

    public class ControlCompetidorBO
    {
        #region Variables Locales
        private static bool usaProxy = false;
        private static string urlProxy = "http://10.10.10.180:8080";
        private static string userProxy = "projas";
        private static string passProxy = "Bnlc0113";
        private static string _strConnectionString = "data source=.;integrated security=SSPI;initial catalog=w1550972_mym";
        #endregion

        private ControlCompetidorBO()
        {
        }

        #region Validación de Competidor
        /// <summary>
        /// Verifica si el Nickname corresponde a un usuario de MercadoLibre
        /// </summary>
        /// <param name="sNick">Nickname de MercadoLibre</param>
        /// <returns>TRUE si el Nickname es válido, de lo contrario FALSE</returns>
        public static bool esNickValido(string sNick)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/users/search?nickname=" + sNick,
                   sLinea,
                   sAux;

            ControlLog.writeLog("[esNickValido] URL pedido: " + sUrl);
            ControlLog.writeLog("[esNickValido] Nick a validar: " + sNick);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = (HttpWebResponse)rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                resp.Close();
                reader.Close();
                ControlLog.writeLog("[esNickValido] Nick válido: " + sNick);
                return true;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[esNickValido] Nick inválido (Excepción): " + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Verifica si el ID corresponde a un usuario de MercadoLibre
        /// </summary>
        /// <param name="sIdML">ID de MercadoLibre</param>
        /// <returns>TRUE si el ID es válido, de lo contrario FALSE</returns>
        public static bool esIdMLValido(string sIdML)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/users/" + sIdML,
                   sLinea,
                   sAux;

            ControlLog.writeLog("[esIdMLValido] ID a validar: " + sIdML);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = (HttpWebResponse)rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                ControlLog.writeLog("[esIdMLValido] ID válido: " + sIdML);
                return true;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[esIdMLValido] ID inválido (Excepción): " + ex.Message);
                return false;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }
        #endregion

        #region Obtención de datos de Competidor
        /// <summary>
        /// Obtiene el ID de usuario de MercadoLibre a partir de su Nickname
        /// </summary>
        /// <param name="sNick">Nickname de MercadoLibre</param>
        /// <returns>ID de MercadoLibre</returns>
        public static string getIdML(string sNick)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/users/search?nickname=" + sNick,
                   sLinea,
                   sAux,
                   sIdML = "";

            ControlLog.writeLog("[getIdML] Obtener ID para: " + sNick);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sIdML = sLinea.Substring(6, sLinea.IndexOf(',') - 6);

                ControlLog.writeLog("[getIdML] ID obtenido: " + sIdML);
                return sIdML;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getIdML] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        /// <summary>
        /// Obtiene el Nickname de usuario de MercadoLibre a partir de su ID
        /// </summary>
        /// <param name="sIdML">ID de MercadoLibre</param>
        /// <returns>Nickname de MercadoLibre</returns>
        public static string getNicknameML(string sIdML)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/users/" + sIdML,
                   sAux,
                   sLinea,
                   sNick = "";
            string[] sParser = new string[50];
            int i = 0;

            ControlLog.writeLog("[getNicknameML] Obtener Nickname para: " + sIdML);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');

                while (!sParser[i].Contains("nickname"))
                    i++;

                sNick = sParser[i].Substring(12, sParser[i].Length - 13);

                ControlLog.writeLog("[getNicknameML] Nickname obtenido: " + sNick);
                return sNick;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getNicknameML] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        /// <summary>
        /// Obtiene el Link a la página del usuario en MercadoLibre a partir de su ID
        /// </summary>
        /// <param name="sIdML">ID de MercadoLibre</param>
        /// <returns>Link a la página del usuario en MercadoLibre</returns>
        public static string getLinkML(string sIdML)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/users/" + sIdML,
                   sAux,
                   sLinea,
                   sLink = "";
            string[] sParser = new string[50];
            int i = 0;

            ControlLog.writeLog("[getLinkML] Obtener link para: " + sIdML);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');

                while (!sParser[i].Contains("permalink"))
                    i++;

                sLink = sParser[i].Substring(13, sParser[i].Length - 14);

                ControlLog.writeLog("[getLinkML] Link obtenido: " + sLink);
                return sLink;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getLinkML] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        /// <summary>
        /// Obtiene las estadísticas de un usuario de MercadoLibre a partir de su ID
        /// </summary>
        /// <param name="sIdML">ID de MercadoLibre</param>
        /// <returns>Instancia de la clase Estadística con los datos obtenidos para el usuario</returns>
        public static Estadistica getEstadisticas(string sIdML)
        {
            Estadistica stat = new Estadistica();
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            DBMethods objConnection = new DBMethods();
            string sUrl = "https://api.mercadolibre.com/users/" + sIdML,
                   sLinea,
                   sAux;
            string[] sParser = new string[50];

            ControlLog.writeLog("[getEstadisticas] Estadísticas para: " + sIdML);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadToEnd();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');

                for (int i = 0; i < sParser.Length; i++)
                {
                    if (sParser[i].Contains("total"))
                    {
                        stat.TxTotal = sParser[i].Substring(8, sParser[i].Length - 8);
                        ControlLog.writeLog("[getEstadisticas] Transacciones totales: " + stat.TxTotal);
                    }

                    if (sParser[i].Contains("completed"))
                    {
                        stat.TxCompletadas = sParser[i].Substring(12, sParser[i].Length - 12);
                        ControlLog.writeLog("[getEstadisticas] Transacciones completadas: " + stat.TxCompletadas);
                    }

                    if (sParser[i].Contains("canceled"))
                    {
                        stat.TxCanceladas = sParser[i].Substring(11, sParser[i].Length - 11);
                        ControlLog.writeLog("[getEstadisticas] Transacciones canceladas: " + stat.TxCanceladas);
                    }

                    if (sParser[i].Contains("site_status"))
                    {
                        if (sParser[i].Contains("active"))
                            stat.Estado = EstadoUsuario.ACTIVO;
                        else
                            if (sParser[i].Contains("pending"))
                                stat.Estado = EstadoUsuario.PENDIENTE;
                            else
                                if (sParser[i].Contains("deactive"))
                                    stat.Estado = EstadoUsuario.INHABILITADO;

                        ControlLog.writeLog("[getEstadisticas] Estado del usuario: " + stat.Estado.ToString());
                    }
                }

                getRankingCalificaciones(sIdML, ref stat);

                stat.CantPublicaciones = Math.Max(getCantPublicaciones(sIdML), objConnection.getCantidadProductos(sIdML));
                ControlLog.writeLog("[getEstadisticas] Cantidad de publicaciones: " + stat.CantPublicaciones.ToString());

                stat.CantCalificaciones = getCantCalificaciones(sIdML);
                ControlLog.writeLog("[getEstadisticas] Cantidad de calificaciones: " + stat.CantCalificaciones.ToString());

                ControlLog.writeLog("[getEstadisticas] Estadísticas obtenidas OK");
                return stat;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getEstadisticas] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static void getRankingCalificaciones(string sIdML, ref Estadistica stat)
        {
            DBMethods objConnection = new DBMethods();
            List<Calificacion> lstCalif = new List<Calificacion>();
            int sIdDB = objConnection.getIdDbCompetidor(sIdML);
            int iCantPositiva = 0,
                iCantNegativa = 0,
                iCantNeutral = 0;

            lstCalif = objConnection.getListaCalificacionesFK(sIdDB.ToString());

            foreach (Calificacion calif in lstCalif)
            {
                switch (calif.Calification)
                {
                    case Calificaciones.POSITIVA:
                        iCantPositiva++;
                        break;
                    case Calificaciones.NEGATIVA:
                        iCantNegativa++;
                        break;
                    case Calificaciones.NEUTRAL:
                        iCantNeutral++;
                        break;
                    default:
                        break;
                }
            }
            stat.RankPositivo = iCantPositiva.ToString();
            stat.RankNegativo = iCantNegativa.ToString();
            stat.RankNeutro = iCantNeutral.ToString();
        }
        #endregion

        #region Procesamiento de Productos
        /// <summary>
        /// Obtiene todos los productos publicados de un competidor
        /// </summary>
        /// <param name="comp">Instancia de la clase Competidor con los datos del competidor a procesar</param>
        /// <returns>Array con instancias de la clase Producto con los datos de cada producto publicado por el competidor</returns>
        public static ArrayList ProcesarConsultaProductos(Competidor comp,TareaPendiente objTareaEnCursoParam)
        {
            int icantpublicacion = comp.getEstadisticas().CantPublicaciones,
                icantprocesadas = 0,
                pagina = 0,
                i = 0,
                j = 0;
            ArrayList myAlProd = new ArrayList();
            Producto prod = null;
            string[] idpublicacion = new string[50];

            ControlLog.writeLog("[ProcesarConsultaProductos] Se encontraron " + icantpublicacion.ToString() + " productos para: " + comp.IdML + " que seran analizados a continuacion...");

            try
            {
                while (icantprocesadas < icantpublicacion)
                {
                    idpublicacion = getIDPublicaciones(comp.IdML, pagina);

                 

                    ///HZ 16-01-2012 - Cuando se informo mayor cantidad de productos
                    /// en comp.getEstadisticas().CantPublicaciones, el getIdPublicaciones PINCHA(BA). Ahora (como fix), si el 
                    /// getIdPublicaciones encuentra menos, devuelve NULL, en vez de saltar una excepcion.
                    /// 
                    /// Entonces, Preguntamos por NULL, para finalizar el recorrido en caso de menor cantidad real de productos...
                    if (idpublicacion == null)
                    {
                        break;
                    }


                    for (j = 0; j < idpublicacion.Length; j++)
                    {
                        if (objTareaEnCursoParam != null)
                        {
                            objTareaEnCursoParam.actualizarEstado(comp.Nickname+": Analizando producto #" + i.ToString() + " de " + icantpublicacion.ToString()+" --> Pagina de ML:"+pagina.ToString(), "En curso");
                        }

                        prod = new Producto();
                        prod = getProducto(idpublicacion[j]);
                        ControlLog.writeLog("[ProcesarConsultaProductos] Producto " + prod.IdPublicacion + " procesado OK");
                        myAlProd.Add(prod);
                        prod = null;
                        i++;
                    }

                    icantprocesadas += idpublicacion.Length;
                    pagina++;
                }

                if (objTareaEnCursoParam != null)
                {
                    objTareaEnCursoParam.actualizarEstado(comp.Nickname + ": " + i .ToString()+ " productos levantados OK", "En curso");
                }

                ControlLog.writeLog("[ProcesarConsultaProductos] Productos obtenidos OK");
                return myAlProd;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ProcesarConsultaProductos] Excepción: " + ex.Message);
                throw ex;
            }
        }

        private static int getCantPublicaciones(string sIdML)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = " http://listado.mercadolibre.com.ar/_CustId_" + sIdML,
                   sLinea,
                   sAux;
            string[] sParser = new string[50];
            int icantpublicaciones = 0,
                i = 0,
                j = 0;

            ControlLog.writeLog("[getCantPublicaciones] Obtener cantidad de publicaciones para: " + sIdML);
            ControlLog.writeLog("[getCantPublicaciones] URL fuente: " + sUrl);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();

                if (sAux.StartsWith("<!DOCTYPE html>") == false)
                {
                    ControlLog.writeLog("[getCantPublicaciones] 1: No se encontraron publicaciones para el usuario");
                    return 0;
                }

                sLinea = HttpUtility.HtmlDecode(sAux);


                while (!sLinea.Contains("list-view-item rowItem"))
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                if (sLinea == null)
                {
                    ControlLog.writeLog("[getCantPublicaciones] 2: No se encontraron publicaciones para el usuario");
                    return 0;
                }

                do
                {
                    i++;
                }
                while ((sLinea.Substring(i, 9) != "<p class=") || (sLinea.Substring(i + 10, 4) != "page"));

                sAux = sLinea.Substring(i, 100);

                sAux = sAux.Substring(sAux.IndexOf("<strong>") + 8, sAux.IndexOf("</strong>") - sAux.IndexOf("<strong>") - 8);

                icantpublicaciones = Convert.ToInt32(sAux);

                ControlLog.writeLog("[getCantPublicaciones] Cantidad obtenida: " + icantpublicaciones);
                return icantpublicaciones;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getCantPublicaciones] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static int getCantAObtener(string sIdML, int pagina)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl,
                   sLinea,
                   sAux,
                   sPagina;
            string[] sParser = new string[50];
            int iCantAObtener = 0,
                iCantDesde = 0,
                iCantHasta = 0,
                i = 0,
                j = 0;

            ControlLog.writeLog("[getCantAObtener] Cantidad de publicaciones a obtener para: " + sIdML);

            try
            {
                if (pagina == 0)
                    sUrl = "http://listado.mercadolibre.com.ar/_CustId_" + sIdML;
                else
                {
                    sPagina = (pagina * 50 + 1).ToString();
                    sUrl = "http://listado.mercadolibre.com.ar/_Desde_" + sPagina + "_CustId_" + sIdML;
                }

                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();

                if (sAux.StartsWith("<!DOCTYPE html>") == false)
                {
                    ControlLog.writeLog("[getCantAObtener] 1: No se encontraron publicaciones para el usuario");
                    return 0;
                }

                sLinea = HttpUtility.HtmlDecode(sAux);


                while (!sLinea.Contains("list-view-item rowItem"))
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                if (sLinea == null)
                {
                    ControlLog.writeLog("[getCantAObtener] 2: No se encontraron publicaciones para el usuario");
                    return 0;
                }

                do
                {
                    i++;
                }
                while ((sLinea.Substring(i, 9) != "<p class=") || (sLinea.Substring(i + 10, 4) != "page"));

                sAux = sLinea.Substring(i, 100);
                sAux = sAux.Substring(sAux.IndexOf("Artículos ") + 10, sAux.IndexOf("-") - sAux.IndexOf("Artículos ") - 10);
                ControlLog.writeLog("[getCantAObtener] Desde: " + sAux);
                iCantDesde = Convert.ToInt32(sAux);

                sAux = sLinea.Substring(i, 100);
                sAux = sAux.Substring(sAux.IndexOf("-") + 1, sAux.IndexOf(" de ") - sAux.IndexOf("-") - 1);
                ControlLog.writeLog("[getCantAObtener] Hasta: " + sAux);
                iCantHasta = Convert.ToInt32(sAux);

                iCantAObtener = iCantHasta - iCantDesde + 1;
                ControlLog.writeLog("[getCantAObtener] Cantidad a obtener: " + iCantAObtener);
                return iCantAObtener;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getCantAObtener] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static string[] getIDPublicaciones(string sIdML, int pagina)
        {
            string[] idpublicacion = new string[50];
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "http://listado.mercadolibre.com.ar/_CustId_" + sIdML,
                   sLinea,
                   sAux,
                   sPagina;
            int iCantAObtener;
            string[] sParser = new string[50];

            ControlLog.writeLog("[getIDPublicaciones] Obtener ID de publicaciones para: " + sIdML + ". En página: " + pagina.ToString() + " del listado");

            try
            {
                if (pagina == 0)
                    sUrl = "http://listado.mercadolibre.com.ar/_CustId_" + sIdML;
                else
                {
                    sPagina = (pagina * 50 + 1).ToString();
                    sUrl = "http://listado.mercadolibre.com.ar/_Desde_" + sPagina + "_CustId_" + sIdML;
                }

                ControlLog.writeLog("[getIDPublicaciones] URL fuente: " + sUrl);

                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                while (!sLinea.Contains("list-view-item rowItem"))
                {
                    sAux = reader.ReadLine();
                    if (sAux == null)
                    {
                        ControlLog.writeLog("[getIDPublicaciones] No hay mas publicaciones. Retornando OK ");
                        return null; //HZ 16-01-2012 - Pincha cuando en ProcesarConsultaProducto le informa mas cantidad de productos que la que realmente tiene.
                    }
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }



                iCantAObtener = getCantAObtener(sIdML, pagina);

                idpublicacion = parsearHTMLPublicaciones(sLinea, iCantAObtener);

                ControlLog.writeLog("[getIDPublicaciones] IDs obtenidos OK");
                return idpublicacion;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getIDPublicaciones] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static string[] parsearHTMLPublicaciones(string sLinea, int iCant)
        {
            string[] idpublicacion = new string[iCant];
            int i = 0,
                j = 0;

            ControlLog.writeLog("[parsearHTMLPublicaciones] Obtener " + iCant + " IDs");

            for (i = 0; i < iCant; i++)
            {
                do
                {
                    j++;
                }
                while (sLinea.Substring(j, 7) != "rowItem");

                idpublicacion[i] = sLinea.Substring(j + 13, 12);
                ControlLog.writeLog("[parsearHTMLPublicaciones] ID obtenido: " + idpublicacion[i]);

                j += 13;
            }
            return idpublicacion;
        }

        private static Producto getProducto(string sIdPublicacion)
        {
            Producto prod = new Producto();

            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/items/" + sIdPublicacion,
                   sLinea,
                   sAux,
                   sAuxMoneda,
                   sAuxEstado;
            string[] sParser = new string[50];

            ControlLog.writeLog("[getProducto] Obtener producto: " + sIdPublicacion);
            ControlLog.writeLog("[getProducto] URL fuente: " + sUrl);
            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');

                for (int i = 0; i < sParser.Length; i++)
                {
                    prod.IdPublicacion = sIdPublicacion;

                    if ((sParser[i].Contains("title")) && (!sParser[i].Contains("subtitle")))
                    {
                        prod.Titulo = sParser[i].Substring(9, sParser[i].Length - 10);
                        ControlLog.writeLog("[getProducto] Título: " + prod.Titulo);
                    }

                    if (sParser[i].Contains("seller_id"))
                    {
                        prod.IdCompetidor = sParser[i].Substring(12, sParser[i].Length - 12);
                        ControlLog.writeLog("[getProducto] ID Competidor: " + prod.IdCompetidor);
                    }

                    if ((sParser[i].Contains("price")) && (!sParser[i].Contains("base_price")))
                    {
                        prod.Precio = sParser[i].Substring(8, sParser[i].Length - 8);
                        prod.Precio = prod.Precio.Replace('.', ',');
                        ControlLog.writeLog("[getProducto] Precio: " + prod.Precio);
                    }

                    if (sParser[i].Contains("currency_id"))
                    {
                        sAuxMoneda = sParser[i].Substring(15, sParser[i].Length - 16);
                        if (sAuxMoneda == "USD")
                            prod.Moneda = Monedas.DOLARES;
                        else
                            if (sAuxMoneda == "ARS")
                                prod.Moneda = Monedas.PESOS;
                            else
                                prod.Moneda = Monedas.Otro;
                        ControlLog.writeLog("[getProducto] Moneda: " + prod.Moneda.ToString());
                    }

                    if (sParser[i].Contains("sold_quantity"))
                    {
                        prod.CantVendido = sParser[i].Substring(16, sParser[i].Length - 16);
                        ControlLog.writeLog("[getProducto] Cantidad vendidos: " + prod.CantVendido);
                    }

                    if (sParser[i].Contains("start_time"))
                    {
                        prod.FechaInicio = sParser[i].Substring(14, 10);
                        ControlLog.writeLog("[getProducto] Fecha inicio: " + prod.FechaInicio);
                    }

                    if (sParser[i].Contains("stop_time"))
                    {
                        prod.FechaFin = sParser[i].Substring(13, 10);
                        ControlLog.writeLog("[getProducto] Fecha fin: " + prod.FechaFin);
                    }

                    if (sParser[i].Contains("condition"))
                    {
                        sAuxEstado = sParser[i].Substring(13, sParser[i].Length - 14);
                        if (sAuxEstado == "new")
                            prod.Estado = EstadoProducto.NUEVO;
                        else
                            prod.Estado = EstadoProducto.USADO;
                        ControlLog.writeLog("[getProducto] Estado: " + prod.Estado.ToString());
                    }

                    if (sParser[i].Contains("permalink"))
                    {
                        prod.Link = sParser[i].Substring(13, sParser[i].Length - 14);
                        ControlLog.writeLog("[getProducto] Link: " + prod.Link);
                    }
                }

                ControlLog.writeLog("[getProducto] Fecha consulta: " + System.DateTime.Now.ToString());

                #region Verificacion LINK
                if (prod.Link == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien el LINK del producto (null). Se setea en NO DISPONIBLE");
                    prod.Link = "NO DISPONIBLE";
                }
                #endregion
                #region Verificacion ESTADO
                if (prod.Estado == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien el ESTADO del producto (null). Se setea en INACTIVO");
                    prod.Estado = EstadoProducto.INACTIVO;
                }
                #endregion
                #region Verificacion Fecha FIN
                if (prod.FechaFin == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien la fecha FIN del producto (null). Se setea en '1/1/2000'");
                    prod.FechaFin = "1/1/2000";
                }
                #endregion
                #region Verificacion PRECIO
                if (prod.Precio == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien el precio del producto (null). Se setea en '0'");
                    prod.Precio = "0";
                }
                #endregion
                #region Verificacion MONEDA
                if (prod.Moneda == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien la moneda del producto (null). Se setea en 'NO DISPONIBLE'");
                    prod.Moneda = Monedas.NO_DISPONIBLE;
                }
                #endregion
                #region Verificacion CANTIDAD VENDIDO
                if (prod.CantVendido == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien la cantidad de ventas del producto (null). Se setea en '0'");
                    prod.CantVendido = "0";
                }
                #endregion
                #region Verificacion Fecha INICIO
                if (prod.FechaInicio == null)
                {
                    ControlLog.writeLog("[getProducto] ERROR: No se obtuvo bien la fecha de inicio de venta del producto (null). Se setea en '1/1/2000'");
                    prod.FechaInicio = "1/1/2000";
                }
                #endregion

                ControlLog.writeLog("[getProducto] Producto obtenido OK");
                return prod;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getProducto] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }


        private static bool existeProductoEnMl(string sIdPublicacion)
        {

            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/items/" + sIdPublicacion,
                   sLinea,
                   sAux,
                   sAuxMoneda,
                   sAuxEstado;
            string[] sParser = new string[50];

            ControlLog.writeLog("[existeProductoEnMl] Obtener producto: " + sIdPublicacion);
            ControlLog.writeLog("[existeProductoEnMl] URL fuente: " + sUrl);
            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');

                for (int i = 0; i < sParser.Length; i++)
                {

                    if ((sParser[i].Contains("status")) && (sParser[i].Contains("active")))
                    {
                        ControlLog.writeLog("[existeProductoEnMl] Producto " + sIdPublicacion + " en estado ACTIVO!");
                        return true;
                    }
                    else if ((sParser[i].Contains("status")) && !(sParser[i].Contains("active")))
                    {
                        ControlLog.writeLog("[existeProductoEnMl] Producto " + sIdPublicacion + " en estado DESCONOCIDO =" + sParser[i]);
                        return false;
                    }

                }


                return false;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getProducto] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }


        /// <summary>
        /// Genera un Array con los productos recibidos que no están en la base de datos
        /// </summary>
        /// <param name="myAlProd">Array con instancias de la clase Producto con los datos de cada producto publicado por el competidor</param>
        /// <param name="strIdDb"> String del ID de la DB del Competidor</param>
        /// <returns>Array con instancias de la clase Producto con los datos de cada producto no encontrado en la base de datos</returns>
        public static ArrayList BuscarProductosNuevos(ArrayList myAlProd, string strIdDb, TareaPendiente objTareaEnCurso)
        {
            ArrayList myAlProdNuevos = new ArrayList();
            Producto prod = new Producto();
            Producto prodnuevo = null;
            DBMethods objConnection = new DBMethods();
            objConnection.strConnectionString = _strConnectionString;


            try
            {
                for (int i = 0; i < myAlProd.Count; i++)
                {
                    prod = (Producto)myAlProd[i];
                    prodnuevo = objConnection.getProductoPK(prod.IdPublicacion);

                    if (objTareaEnCurso != null)
                    {
                        objTareaEnCurso.actualizarEstado(" Revisando productos existentes en la DB ("+i.ToString()+"/"+myAlProd.Count.ToString()+")", "En curso");
                    }

                    if (prodnuevo.Estado == EstadoProducto.INEXISTENTE)
                    {
                        objConnection.crearProducto(prod, strIdDb);
                        ControlLog.writeLog("[BuscarProductosNuevos] Se agregó producto " + prod.IdPublicacion + " a la tabla (NUEVO)");
                        myAlProdNuevos.Add(prod);
                    }
                }

                ControlLog.writeLog("[BuscarProductosNuevos] Proceso OK. Productos nuevos: " + myAlProdNuevos.Count.ToString());
                return myAlProdNuevos;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[BuscarProductosNuevos] Excepción: " + ex.Message);
                throw ex;
            }
        }

        /// <summary>
        /// Genera un Array con los productos no recibidos que están en la base de datos
        /// </summary>
        /// <param name="myAlProd">Array con instancias de la clase Producto con los datos de cada producto publicado por el competidor</param>
        /// <returns>Array con instancias de la clase Producto con los datos de cada producto no recibido</returns>
        public static ArrayList BuscarProductosNoEstan(ArrayList myAlProd, TareaPendiente objTareaEnCurso)
        {
            ArrayList myAlProdNoEstan = new ArrayList();
            ArrayList myAlBD = new ArrayList();
            string sIdML = ((Producto)myAlProd[0]).IdCompetidor;
            Producto prod = null;
            bool encontrado;
            DBMethods objConnection = new DBMethods();

            try
            {
                myAlBD = objConnection.getProductoFK(sIdML);

                for (int i = 0; i < myAlBD.Count; i++)
                {
                    encontrado = false;
                    ControlLog.writeLog("[BuscarProductosNoEstan] Tabla DB: Producto " + ((Producto)myAlBD[i]).IdPublicacion);

                    if (objTareaEnCurso != null)
                    {
                        objTareaEnCurso.actualizarEstado(" Revisando productos que no estan en la DB (" + i.ToString() + "/" + myAlBD.Count.ToString() + ")", "En curso");
                    }

                    #region Primera ronda de busqueda de Producto - Listado propio de Mercado Libre - Busqueda ONLINE
                    for (int j = 0; j < myAlProd.Count; j++)
                    {
                        //   ControlLog.writeLog("[BuscarProductosNoEstan] Productos encontrados " + ((Producto)myAlProd[j]).IdPublicacion);

                        if (((Producto)myAlBD[i]).IdPublicacion == ((Producto)myAlProd[j]).IdPublicacion)
                        {
                            ControlLog.writeLog("[BuscarProductosNoEstan] Productos matchean! " + ((Producto)myAlBD[i]).IdPublicacion + ":" + ((Producto)myAlProd[j]).IdPublicacion);
                            encontrado = true;
                            break;
                        }
                    }
                    #endregion
                    #region Segunda ronda de Busqueda de Producto - Publicaciones de Calificaciones - Busqueda LOCAL
                    if (!encontrado)  ///Si todavia no encontre el producto en la primera busqueda
                    {
                        List<string> lstIdPublicacionCalificaciones = objConnection.getProductoDeCalificaciones(objConnection.getIdDbCompetidor(sIdML).ToString());

                        foreach (string strIdPublicacionCalificaciones in lstIdPublicacionCalificaciones)
                        {
                            ///Primero me fijo si el producto en cuestion está NOMINALMENTE en la lista 
                            ///(puede ser que siag existiendo como que no)

                            ControlLog.writeLog("[BuscarProductosNoEstan] Productos encontrados en calif. " + strIdPublicacionCalificaciones);

                            if (((Producto)myAlBD[i]).IdPublicacion == strIdPublicacionCalificaciones)
                            {
                                ControlLog.writeLog("[BuscarProductosNoEstan] Productos matchean (calif) " + ((Producto)myAlBD[i]).IdPublicacion + ":" + strIdPublicacionCalificaciones);
                                ///OK, lo encontro.. pero.. sigue existiendo ese producto??
                                if (ControlCompetidorBO.existeProductoEnMl(((Producto)myAlBD[i]).IdPublicacion))
                                {
                                    encontrado = true;
                                }

                                break;
                            }
                        }
                    }
                    #endregion


                    if (!encontrado)
                    {
                        prod = new Producto();
                        prod = (Producto)myAlBD[i];
                        myAlProdNoEstan.Add(prod);
                        prod = null;
                    }
                }

                for (int k = 0; k < myAlProdNoEstan.Count; k++)
                {
                    objConnection.borrarProducto(((Producto)myAlProdNoEstan[k]).IdPublicacion);
                }

                ControlLog.writeLog("[BuscarProductosNoEstan] Proceso OK");
                return myAlProdNoEstan;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[BuscarProductosNoEstan] Excepción: " + ex.Message);
                throw ex;
            }
        }

        /// <summary>
        /// Genera un Array con los productos recibidos que tienen distinto precio y/o moneda en la base de datos
        /// </summary>
        /// <param name="myAlProd">Array con instancias de la clase Producto con los datos de cada producto publicado por el competidor</param>
        /// <returns>Array con instancias de la clase Producto con los datos de cada producto que tiene diferencia en el precio y/o moneda</returns>
        public static ArrayList BuscarProductosConCambios(ArrayList myAlProd, TareaPendiente objTareaEnCurso)
        {
            ArrayList myAlProdCambios = new ArrayList();
            Producto prod = new Producto();
            Producto auxprod = new Producto();
            ProductoCambio prodcambio = null;
            DBMethods objConnection = new DBMethods();

            try
            {
                for (int i = 0; i < myAlProd.Count; i++)
                {
                    prod = (Producto)myAlProd[i];
                    auxprod = objConnection.getProductoPK(prod.IdPublicacion);

                    if (objTareaEnCurso != null)
                    {
                        objTareaEnCurso.actualizarEstado(" Revisando productos con cambios en la DB (" + i.ToString() + "/" + myAlProd.Count.ToString() + ")", "En curso");
                    }

                    if ((prod.Precio != auxprod.Precio) || (prod.Moneda != auxprod.Moneda))
                    {
                        prodcambio = new ProductoCambio();

                        prodcambio.Prod = prod;
                        prodcambio.MonedaAnterior = auxprod.Moneda;
                        prodcambio.PrecioAnterior = auxprod.Precio;

                        objConnection.modificarProducto(prod);
                        ControlLog.writeLog("[BuscarProductosConCambios] Se agregó producto con cambios: " + prodcambio.Prod.IdPublicacion);

                        myAlProdCambios.Add(prodcambio);

                        prodcambio = null;
                    }
                }

                ControlLog.writeLog("[BuscarProductosConCambios] Proceso OK");
                return myAlProdCambios;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[BuscarProductosConCambios] Excepción: " + ex.Message);
                throw ex;
            }
        }
        #endregion

        #region Procesamiento de Calificaciones
        /// <summary>
        /// Obtiene todas las calificaciones realizadas a un competidor
        /// </summary>
        /// <param name="comp">Instancia de la clase Competidor con los datos del competidor a procesar</param>
        /// <param name="strCantidadMaxima"> String de Cantidad Maxima de Calificaciones</param>
        /// <returns>Array con instancias de la clase Calificacion con los datos de cada calificación realizada al competidor</returns>
        public static ArrayList ProcesarConsultaCalificaciones(Competidor comp, string strCantidadMaxima, TareaPendiente objTareaEnCurso)
        {
            ArrayList myAlCalif = new ArrayList();
            Calificacion calif = null;
            List<Calificacion> lstCalifRecientes = new List<Calificacion>();
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            DBMethods objConnection = new DBMethods();
            string sUrl = "http://www.mercadolibre.com.ar/jm/profile?act=ver&id=" + comp.IdML + "&baseLista=1&tipo=0&oper=B&orden=1#head_califs",
                   sLinea,
                   sAux,
                   sFechaReciente = "";
            int icantcalificaciones = comp.refrescarEstadisticas().CantCalificaciones,
                icantprocesadas = 0,
                icantpagina = 25,
                icantactual = 0,
                intCantidadMaximaDeCalificaciones = 0,
                icantaux = 0;
            bool bNuevas = false;

            ControlLog.writeLog("[ProcesarConsultaCalificaciones] Calificaciones para: " + comp.IdML);
            ControlLog.writeLog("[ProcesarConsultaCalificaciones] URL fuente: " + sUrl);

            if (strCantidadMaxima == null)
                bNuevas = true;

            try
            {
                if (!bNuevas)
                    intCantidadMaximaDeCalificaciones = Convert.ToInt32(strCantidadMaxima);
            }
            catch (Exception ee)
            {
                ControlLog.writeLog("[ProcesarConsultaCalificaciones] No se pudo convertir la cantidad Maxima de Calificaciones: " + ee.Message);
                throw ee;
            }

            if (!bNuevas)
            {
                if (intCantidadMaximaDeCalificaciones > icantcalificaciones)
                    intCantidadMaximaDeCalificaciones = icantcalificaciones;
            }
            else
            {
                intCantidadMaximaDeCalificaciones = icantcalificaciones;
                lstCalifRecientes = objConnection.getCalificacionMasReciente(objConnection.getIdDbCompetidor(comp.IdML).ToString());
                try
                {
                    sFechaReciente = lstCalifRecientes[0].Fecha;
                }
                catch (Exception ex)
                {
                    ControlLog.writeLog("[ProcesarConsultaCalificaciones] No hay calificaciones en la base de datos: " + ex.Message);
                    sFechaReciente = null;
                }
            }

            try
            {
                while (icantprocesadas < intCantidadMaximaDeCalificaciones)
                {
                    icantaux = icantprocesadas + 1;
                    sUrl = "http://www.mercadolibre.com.ar/jm/profile?act=ver&id=" + comp.IdML + "&baseLista=" + icantaux + "&tipo=0&oper=B&orden=1#head_califs";
                    rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                    ControlLog.writeLog("[ProcesarConsultaCalificaciones] Url a analizar: " + sUrl);
                    rqst.Method = "GET";
                    /* COMIENZO PROXY */
                    if (usaProxy)
                    {
                        WebProxy proxy = new WebProxy();
                        Uri address = new Uri(urlProxy);
                        proxy.Address = address;
                        proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                        rqst.Proxy = proxy;
                    }
                    /* FIN PROXY */
                    resp = rqst.GetResponse();
                    reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);

                    while ((icantprocesadas < intCantidadMaximaDeCalificaciones) && (icantactual < icantpagina))
                    {

                        if (objTareaEnCurso != null)
                        {
                            objTareaEnCurso.actualizarEstado(" Procesando calificaciones  (" + icantprocesadas.ToString() + "/" + intCantidadMaximaDeCalificaciones.ToString() + ")", "En curso");
                        }


                        while (!sLinea.Contains("content_box"))
                        {
                            sAux = reader.ReadLine();

                            if (sAux == null)
                            {
                                resp.Close();
                                reader.Close();
                                ControlLog.writeLog("[ProcesarConsultaCalificaciones] No se encontraron calificaciones para el usuario");
                                return null;
                            }

                            sLinea = HttpUtility.HtmlDecode(sAux);
                        }
                        calif = new Calificacion();

                        calif = getCalificacion(ref reader);

                        if (bNuevas && sFechaReciente != null)
                        {
                            if (calif.Fecha.Equals(sFechaReciente))
                            {
                                if (!existeCalificacionEnDB(lstCalifRecientes, calif))
                                {
                                    ControlLog.writeLog("[ProcesarConsultaCalificaciones] Calificación de usuario" + calif.NickUsuario + " para producto " + calif.Prod.IdPublicacion + " procesada OK");
                                    myAlCalif.Add(calif);
                                }
                            }
                            else
                            {
                                ControlLog.writeLog("[ProcesarConsultaCalificaciones] Fecha Calificacion = " + calif.Fecha + " - Fecha reciente = " + sFechaReciente);
                                if (Convert.ToDateTime(calif.Fecha) < Convert.ToDateTime(sFechaReciente))
                                {
                                    myAlCalif.Add(calif);
                                    ControlLog.writeLog("[ProcesarConsultaCalificaciones] Calificación de usuario" + calif.NickUsuario + " para producto " + calif.Prod.IdPublicacion + " procesada OK");
                                }
                                else
                                {
                                    ControlLog.writeLog("[ProcesarConsultaCalificaciones] Calificación es anterior a la última existente en la DB. Se retornan hasta aquí.");
                                    return myAlCalif;
                                }
                            }
                        }
                        else
                        {
                            myAlCalif.Add(calif);
                            ControlLog.writeLog("[ProcesarConsultaCalificaciones] Calificación de usuario " + calif.NickUsuario + " para producto " + calif.Prod.IdPublicacion + " procesada OK");
                        }

                        icantprocesadas++;
                        icantactual++;

                        sAux = reader.ReadLine();
                        sLinea = HttpUtility.HtmlDecode(sAux);
                    }
                    icantactual = 0;

                    resp.Close();
                    reader.Close();
                }

                ControlLog.writeLog("[ProcesarConsultaCalificaciones] Proceso OK");
                return myAlCalif;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ProcesarConsultaCalificaciones] Excepción: " + ex.Message);
                throw ex;
            }
        }

        private static bool existeCalificacionEnDB(List<Calificacion> lstCalifRecientes, Calificacion calif)
        {
            bool existe = false;

            foreach (Calificacion auxCalif in lstCalifRecientes)
            {
                if (auxCalif.Fecha.Equals(calif.Fecha) &&
                    auxCalif.Prod.IdPublicacion.Equals(calif.Prod.IdPublicacion) &&
                    auxCalif.NickUsuario.Equals(calif.NickUsuario))
                    existe = true;
            }

            return existe;
        }

        private static int getCantCalificaciones(string sIdML)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "http://www.mercadolibre.com.ar/jm/profile?act=ver&id=" + sIdML + "&baseLista=1&tipo=0&oper=B&orden=1#head_califs",
                   sLinea,
                   sAux;
            int icantcalificaciones = 0,
                i = 0,
                j = 0;

            ControlLog.writeLog("[getCantCalificaciones] Obtener cantidad de calificaciones para: " + sIdML);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadLine();
                sLinea = HttpUtility.HtmlDecode(sAux);

                while ((!sLinea.Contains("<div id=")) || (!sLinea.Contains("ordena")))
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                i = j = sLinea.IndexOf("<b>") + 3;
                do
                {
                    j++;
                }
                while (sLinea[j] != '<');

                sAux = sLinea.Substring(i, j - i);
                icantcalificaciones = Convert.ToInt32(sAux);

                ControlLog.writeLog("[getCantCalificaciones] Cantidad obtenida: " + icantcalificaciones.ToString());
                return icantcalificaciones;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getCantCalificaciones] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static Calificacion getCalificacion(ref StreamReader reader)
        {
            Calificacion calif = new Calificacion();
            DateTime fechaconsulta = DateTime.Today;
            DateTime fechacalificacion;
            TimeSpan ts = new TimeSpan();
            DBMethods objConnection = new DBMethods();
            string sLinea = "",
                   sAux,
                   sIDProd,
                   sIDUser;
            int i = 0,
                j = 0;

            ControlLog.writeLog("[getCalificacion] Inicio de obtener calificación");

            try
            {
                while (!sLinea.Contains("icono")) /* PARA LA PUNTUACION */
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                if (sLinea.Contains("pos"))
                    calif.Calification = Calificaciones.POSITIVA;
                else
                    if (sLinea.Contains("neu"))
                        calif.Calification = Calificaciones.NEUTRAL;
                    else
                        if (sLinea.Contains("neg"))
                            calif.Calification = Calificaciones.NEGATIVA;

                ControlLog.writeLog("[getCalificacion] Calificación: " + calif.Calification);

                while (!sLinea.Contains("box_texto"))   /* PARA EL COMENTARIO */
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                i = sLinea.IndexOf("box_texto") + 12;
                j = sLinea.LastIndexOf('<') - 1;

                if (j < i)
                    calif.Comentario = sLinea.Substring(i, sLinea.Length - i);
                else
                    calif.Comentario = sLinea.Substring(i, j - i);

                ControlLog.writeLog("[getCalificacion] Comentario: " + calif.Comentario);

                do
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }
                while ((!sLinea.Contains("fecha")) && (!sLinea.Contains("<a href=-")));   /* PARA LA FECHA */

                calif.Fecha = sLinea.Substring(16, 10);
                ControlLog.writeLog("[getCalificacion] Fecha: " + calif.Fecha);


                while (!sLinea.Contains("compra_texto"))    /* PARA EL LINK Y NICK DEL USUARIO */
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }

                calif.LinkUsuario = "http://www.mercadolibre.com.ar" + sLinea.Substring(32, sLinea.IndexOf("\">", 32) - 32);
                ControlLog.writeLog("[getCalificacion] Link usuario: " + calif.LinkUsuario);

                i = calif.LinkUsuario.IndexOf("?id=") + 4;
                j = calif.LinkUsuario.IndexOf("&oper=S");

                sIDUser = calif.LinkUsuario.Substring(i, j - i);

                calif.NickUsuario = getNicknameML(sIDUser);
                ControlLog.writeLog("[getCalificacion] Nickname usuario: " + calif.NickUsuario);

                do
                {
                    sAux = reader.ReadLine();
                    sLinea = HttpUtility.HtmlDecode(sAux);
                }
                while (!sLinea.Contains("compr"));

                if (sLinea.Contains("<a href="))
                {
                    ControlLog.writeLog("[getCalificacion] <a href= encontrado ");
                    ControlLog.writeLog("[getCalificacion] sLinea.IndexOf(\" & id = \")  = " + sLinea.IndexOf("&id=").ToString());
                    sIDProd = "MLA" + sLinea.Substring(sLinea.IndexOf("&id=") + 4, 9);
                    ControlLog.writeLog("[getCalificacion] Identificador de producto a OBTENER = " + sIDProd);
                    ///TODO: Se obtiene el producto via API
                    calif.Prod = getProducto(sIDProd);
                    ///TODO: Se deberia obtener obtener el producto via scrapping... cuando no lo puedo obtener via API

                    Producto objProducto = null;
                    ControlLog.writeLog("[getCalificacion] Buscar producto: " + sIDProd + " en la DB.");
                    objProducto = objConnection.getProductoPK(sIDProd);

                    if (objProducto.Estado == EstadoProducto.INEXISTENTE)
                    {
                        objProducto = calif.Prod;
                        ControlLog.writeLog("[getCalificacion] PRODUCTO INEXISTENTE: ID de Producto " + sIDProd + " no existe en DB, se averigua si esta ACTIVO en ML.... ");
                        if (ControlCompetidorBO.existeProductoEnMl(sIDProd))
                        {
                            ControlLog.writeLog("[getCalificacion] ID de Producto no existía en DB, y si estaba ACTIVO en ML. Se da de alta: " + objProducto.IdPublicacion);
                            int IdDB = objConnection.getIdDbCompetidor(objProducto.IdCompetidor);
                            objConnection.crearProducto(objProducto, IdDB.ToString());
                            Reporte.arrLstProductosNuevos.Add(objProducto);
                            Reporte.arrLstProductosAll.Add(objProducto);
                        }
                        else
                        {
                            ControlLog.writeLog("[getCalificacion] ID de Producto " + sIDProd + " no existe en DB, y no esta ACTIVO en ML. No se agregara a la tabla de Productos. ");

                        }
                    }
                    ControlLog.writeLog("[getCalificacion] ID Producto de la calificación: " + calif.Prod.IdPublicacion);
                }
                else
                {
                    calif.Prod = new Producto();
                    ControlLog.writeLog("[getCalificacion] sLinea.IndexOf('$')  = " + sLinea.IndexOf('$').ToString());

                    calif.Prod.IdPublicacion = "NO DISPONIBLE";
                    if (sLinea.IndexOf('$') == -1)
                    {
                        calif.Prod.Titulo = sLinea.Substring(/*0*/sLinea.IndexOf("compr") + 7, Math.Min(sLinea.Length, /*30*/ 90) - (sLinea.IndexOf("compr") + 7));  //HZ v2.0.2.0
                        calif.Prod.Precio = "NO DISPONIBLE";
                    }
                    else
                    {
                        calif.Prod.Titulo = sLinea.Substring(/*0*/ sLinea.IndexOf("compr") + 7, sLinea.IndexOf('$') - (sLinea.IndexOf("compr") + 7));  //HZ v2.0.2.0
                        calif.Prod.Precio = sLinea.Substring(sLinea.IndexOf('$') + 1, sLinea.IndexOf('.', sLinea.IndexOf('$')) + 3 - (sLinea.IndexOf('$') + 1));
                    }
                    calif.Prod.CantVendido = "NO DISPONIBLE";
                    calif.Prod.Estado = EstadoProducto.INEXISTENTE;
                    calif.Prod.Link = "NO DISPONIBLE";
                    calif.Prod.Moneda = Monedas.Otro;
                    ///TODO: Falta agregar el precio real del producto               
                    ControlLog.writeLog("[getCalificacion] No se encontro el producto: " + calif.Prod.Titulo);
                }

                ControlLog.writeLog("[getCalificacion] Calificación obtenida OK");
                return calif;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getCalificacion] Excepción: " + ex.Message);
                throw ex;
            }
        }
        #endregion

        #region Procesamiento de Preguntas y Respuestas
        /// <summary>
        /// Obtiene todas las preguntas y respuestas realizadas para cada producto publicado por un competidor
        /// </summary>
        /// <param name="myAlProd">Array con instancias de la clase Producto con los datos de cada producto publicado por el competidor</param>
        /// <returns>Array con instancias de la clase PreguntasRespuestas con los datos de cada pregunta realizada para cada producto publicado por el competidor</returns>
        public static ArrayList ProcesarPreguntasRespuestas(ArrayList myAlProd)
        {
            ArrayList myAlPregResp = new ArrayList();
            Producto prod = null;
            PreguntasRespuestas[] pregs = null;
            int iCant = 0;

            ControlLog.writeLog("[ProcesarPreguntasRespuestas] Inicio de obtener preguntas y respuestas");

            try
            {
                for (int i = 0; i < myAlProd.Count; i++)
                {
                    prod = new Producto();
                    prod = (Producto)myAlProd[i];

                    iCant = getCantPregRespPublicacion(prod.IdPublicacion);

                    pregs = new PreguntasRespuestas[iCant];

                    pregs = getPregRespPublicacion(prod, iCant);

                    foreach (PreguntasRespuestas preg in pregs)
                    {
                        myAlPregResp.Add(preg);
                    }

                    pregs = null;
                    prod = null;
                }

                ControlLog.writeLog("[ProcesarPreguntasRespuestas] Proceso OK");
                return myAlPregResp;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ProcesarPreguntasRespuestas] Excepción: " + ex.Message);
                throw ex;
            }
        }

        private static int getCantPregRespPublicacion(string sIDPublicacion)
        {
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/questions/search?item_id=" + sIDPublicacion,
                   sLinea,
                   sAux;
            int icantpregrespproducto = 0,
                i = 0,
                j = 0;

            ControlLog.writeLog("[getCantPregRespPublicacion] Inicio de obtener cantidad de preguntas y respuestas");

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadToEnd();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sAux = sLinea.Substring(9, sLinea.IndexOf(',') - 9);
                icantpregrespproducto = Convert.ToInt32(sAux);

                ControlLog.writeLog("[getCantPregRespPublicacion] Cantidad obtenida: " + icantpregrespproducto.ToString());
                return icantpregrespproducto;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getCantPregRespPublicacion] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }

        private static PreguntasRespuestas[] getPregRespPublicacion(Producto prod, int iCant)
        {
            PreguntasRespuestas[] pregs = new PreguntasRespuestas[iCant];
            PreguntasRespuestas preg = null;
            HttpWebRequest rqst = null;
            WebResponse resp = null;
            StreamReader reader = null;
            string sUrl = "https://api.mercadolibre.com/questions/search?item_id=" + prod.IdPublicacion,
                   sLinea,
                   sAux;
            string[] sParser = new string[600];
            int icantprocesadas = 0,
                i = 0,
                j = 0;
            double aux = 0;
            bool fecharesp = false,
                 textoresp = false,
                 completo = false;

            ControlLog.writeLog("[getPregRespPublicacion] Obtener preguntas y respuestas para producto: " + prod.IdPublicacion);

            try
            {
                rqst = (HttpWebRequest)WebRequest.Create(sUrl);
                rqst.Method = "GET";
                /* COMIENZO PROXY */
                if (usaProxy)
                {
                    WebProxy proxy = new WebProxy();
                    Uri address = new Uri(urlProxy);
                    proxy.Address = address;
                    proxy.Credentials = new NetworkCredential(userProxy, passProxy);
                    rqst.Proxy = proxy;
                }
                /* FIN PROXY */
                resp = rqst.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);

                sAux = reader.ReadToEnd();
                sLinea = HttpUtility.HtmlDecode(sAux);

                sParser = sLinea.Split(',');


                while ((icantprocesadas < iCant) && (i < sParser.Length))
                {
                    preg = new PreguntasRespuestas();
                    preg.Prod = prod;

                    while (!completo)
                    {
                        if ((sParser[i].Contains("id")) && (!sParser[i].Contains("item_id")) && (!sParser[i].Contains("seller_id")))
                        {
                            j = sParser[i].IndexOf("id") + 4;
                            sAux = sParser[i].Substring(j, sParser[i].Length - j);
                            try
                            {
                                aux = Convert.ToDouble(sAux);
                                preg.IDPregResp = sAux;
                                ControlLog.writeLog("[getPregRespPublicacion] ID pregunta / respuesta: " + preg.IDPregResp);
                            }
                            catch (Exception ex) { }
                        }

                        if ((fecharesp) && (sParser[i].Contains("date_created")))
                        {
                            preg.FechaPregunta = sParser[i].Substring(16, 10);
                            ControlLog.writeLog("[getPregRespPublicacion] Fecha pregunta: " + preg.FechaPregunta);
                        }

                        if ((textoresp) && (sParser[i].Contains("text")))
                        {
                            preg.TextoPregunta = sParser[i].Substring(8, sParser[i].Length - 8);

                            while (!sParser[i].Contains("}"))
                            {
                                i++;
                                preg.TextoPregunta += "," + sParser[i];
                            }

                            preg.TextoPregunta = preg.TextoPregunta.Substring(0, preg.TextoPregunta.Length - 2);
                            ControlLog.writeLog("[getPregRespPublicacion] Texto pregunta: " + preg.TextoPregunta);

                            completo = true;
                        }

                        if ((!fecharesp) && (sParser[i].Contains("date_created")))
                        {
                            preg.FechaRespuesta = sParser[i].Substring(26, 10);
                            ControlLog.writeLog("[getPregRespPublicacion] Fecha respuesta: " + preg.FechaRespuesta);
                            fecharesp = true;
                        }

                        if ((!textoresp) && (sParser[i].Contains("text")))
                        {
                            preg.TextoRespuesta = sParser[i].Substring(8, sParser[i].Length - 8);


                            while (!sParser[i].Contains("}"))
                            {
                                i++;
                                preg.TextoRespuesta += "," + sParser[i];
                            }

                            preg.TextoRespuesta = preg.TextoRespuesta.Substring(0, preg.TextoRespuesta.Length - 2);
                            ControlLog.writeLog("[getPregRespPublicacion] Texto respuesta: " + preg.TextoRespuesta);

                            textoresp = true;
                        }

                        i++;
                    }

                    pregs[icantprocesadas] = preg;

                    preg = null;

                    fecharesp = false;
                    textoresp = false;
                    completo = false;

                    icantprocesadas++;

                }

                ControlLog.writeLog("[getPregRespPublicacion] Proceso OK");
                return pregs;
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[getPregRespPublicacion] Excepción: " + ex.Message);
                throw ex;
            }
            finally
            {
                resp.Close();
                reader.Close();
            }
        }
        #endregion
    }

    public class ControlCompetidorCrearCompetidorAsyncHandler : System.Web.IHttpAsyncHandler
    {
        public static string strMensajeDeError;

        TareaPendiente objTareaARealizar;
        private AsyncTaskDelegate del;
        private AsyncTaskDelegate delTest;
        protected delegate void AsyncTaskDelegate(HttpContext context);
        Competidor objHandlerCompetidor;


        public ControlCompetidorCrearCompetidorAsyncHandler()
        {

        }

        public void ProcessRequest(HttpContext context)
        {
            DBMethods objConnection = new DBMethods();
            int intDbIdCompetidor = 0;
            try
            {
                
                #region Averiguacion de Usuario
                objTareaARealizar.actualizarEstado("Averiguando usuario: " + objHandlerCompetidor.Nickname, "En curso");
                try
                {
                    if (ControlCompetidorBO.esNickValido(objHandlerCompetidor.Nickname) == false)
                    {
                        ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error creando competidor: Nickname no existe en Mercado Libre. Verifique el nickname ingresado");
                        objTareaARealizar.actualizarEstado("Nickname no existe en Mercado Libre. Verifique el nickname ingresado", "ERROR");
                        Thread.Sleep(60000);                        
                        return;
                    }

                }
                catch (Exception ee)
                {                    
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error al averiguar el nickname de usuario: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error al averiguar el nickname de usuario: " + ee.Message, "ERROR");
                    Thread.Sleep(60000); 
                    return;
                }

                #endregion
                #region Obtencion del ID de ML
                objTareaARealizar.actualizarEstado("Obteniendo ID de ML: " + objHandlerCompetidor.Nickname, "En curso");
                try
                {
                    objHandlerCompetidor.IdML = ControlCompetidorBO.getIdML(objHandlerCompetidor.Nickname);
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error al conseguir el ID de usuario: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error al conseguir el ID de usuario: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);                                        
                    
                    return;
                }
                #endregion
                #region Obtener Estadisticas Competidor
                objTareaARealizar.actualizarEstado("Obteniendo Estadisticas de (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
                try
                {
                    objHandlerCompetidor.refrescarEstadisticas();
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error al conseguir estadisticas de usuario: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error al conseguir estadisticas de usuario: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);

                    return;
                }

                #endregion
                #region Agregar Link de Usuario
                objTareaARealizar.actualizarEstado("Obteniendo link de usuario (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                try
                {
                    objHandlerCompetidor.Link = ControlCompetidorBO.getLinkML(objHandlerCompetidor.IdML);
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Excepción obteniendo Link de Usuario ML: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Excepción obteniendo Link de Usuario ML: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);

                    return;
                }
                #endregion
                #region Agregar Competidor
                objTareaARealizar.actualizarEstado("Agregando competidor (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                try
                {
                    if (objConnection.existeCompetidor(objHandlerCompetidor.IdML) == false)
                    {
                        objConnection.crearCompetidor(objHandlerCompetidor);
                    }
                    else
                    {
                        ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Usuario ya existe en la Base de Datos");
                        objTareaARealizar.actualizarEstado("Usuario ya existe en la Base de Datos", "ERROR");
                        Thread.Sleep(60000);                                              
                        return;
                    }
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error agregando Competidor: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error agregando Competidor: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);
                    return;                   
                }

                #endregion
                #region Agregar Productos del Competidor
                objTareaARealizar.actualizarEstado("Agregando productos de (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                try
                {
                    intDbIdCompetidor = objConnection.getIdDbCompetidor(objHandlerCompetidor.IdML);
                    ArrayList myAlProd = new ArrayList();
                    myAlProd = ControlCompetidorBO.ProcesarConsultaProductos(objHandlerCompetidor,this.objTareaARealizar);

                    Producto objProducto = null;

                    for (int i = 0; i < myAlProd.Count; i++)
                    {
                        objProducto = new Producto();
                        objProducto = (Producto)myAlProd[i];
                        objConnection.crearProducto(objProducto, intDbIdCompetidor.ToString());
                        objProducto = null;
                    }

                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error agregando Productos iniciales del Competidor: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error agregando Productos iniciales del Competidor: " + ee.Message, "ERROR");
                    Thread.Sleep(60000); 
                    return;
                }
                #endregion
                #region Crear carpeta del competidor
                //string sPath = MapPath("Competidores");
                objTareaARealizar.actualizarEstado("Creando carpeta de calificaciones de (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                string sPath = ControlSesion.session("pathCompetidores");
                try
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Path de Carpeta a crear para el competidor " + sPath + "\\" + objHandlerCompetidor.IdML);
                    System.IO.Directory.CreateDirectory(sPath + "\\" + objHandlerCompetidor.IdML);
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error generando carpeta de Competidor: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error generando carpeta de Competidor: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);
                    return;
                }
                #endregion
                #region Obtener Calificaciones
                objTareaARealizar.actualizarEstado("Obteniendo calificaciones de (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                try
                {
                    Reporte.arrLstProductosAll = new ArrayList();
                    Reporte.arrLstProductosNuevos = new ArrayList();



                    ArrayList arrLstCalificaciones;
                    Calificacion objCalificacion = null;
                    arrLstCalificaciones = ControlCompetidorBO.ProcesarConsultaCalificaciones(objHandlerCompetidor, ControlSesion.session("cantidadMaximaDeCalificaciones"),this.objTareaARealizar);

                    if (arrLstCalificaciones != null)
                    {

                        for (int i = 0; i < arrLstCalificaciones.Count; i++)
                        {
                            objCalificacion = (Calificacion)arrLstCalificaciones[i];
                            objTareaARealizar.actualizarEstado(objHandlerCompetidor.Nickname+": Creando calificaciones (" + i.ToString() + "/" + arrLstCalificaciones.Count.ToString() + "): ", "En curso");
             
                            objConnection.crearCalificacion(objCalificacion, intDbIdCompetidor.ToString());
                            objCalificacion = null;
                        }
                    }
                  
                    Reporte.arrLstProductosAll = null;
                    Reporte.arrLstProductosNuevos = null;
                }
                catch (Exception ee)
                {
                    ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequest] Error agregando calificaciones de Competidor: " + ee.Message);
                    objTareaARealizar.actualizarEstado("Error agregando calificaciones de Competidor: " + ee.Message, "ERROR");
                    Thread.Sleep(60000);
                    return;
                }
                #endregion
                #region Actualizar GUI
                objTareaARealizar.actualizarEstado("Actualizando GUI para (" + objHandlerCompetidor.IdML + "): " + objHandlerCompetidor.Nickname, "En curso");
              
                ControlSesion.session("actualizarGUIPorCreacionDeCompetidor", "TRUE");
                #endregion
            }
            catch (CompetidorException compEx)
            {
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequestCrearCompetidor] EXCEPCION de creacion de Competidores: " + compEx.Message);
                objTareaARealizar.actualizarEstado(compEx.Message, "ERROR");
                Thread.Sleep(60000);
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:ProcessRequestCrearCompetidor] Excepcion Procesando Tarea de creacion de Competidores: " + ex.Message);
            }
        }

      
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object obj)
        {
            this.del = new AsyncTaskDelegate(ProcessRequest);
            objHandlerCompetidor = (Competidor)obj;
            AsyncCallback objCallBack = new AsyncCallback(callbackCrearCompetidor);
            objTareaARealizar = new TareaPendiente();
            objTareaARealizar.crearTarea(ControlSesion.session(ControlSesion.UsuarioLogin), "Competidores", "Creando competidor  [" + System.DateTime.Now.ToString() + "]");
            return del.BeginInvoke(context, objCallBack, obj);


        }

    

        public void ProcessRequestTest(HttpContext context)
        {
            try
            {
                strMensajeDeError = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                ControlLog.writeLog("[ControlImportacionAsyncHandler:ProcessRequestTest] Soy " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
            }
            catch (Exception ex)
            {
                strMensajeDeError = " Excepcion = " + ex.Message;
            }
        }

        public IAsyncResult BeginProcessRequestTest(HttpContext context, AsyncCallback cb, object obj)
        {
            this.delTest = new AsyncTaskDelegate(ProcessRequestTest);


            IAsyncResult objResult = delTest.BeginInvoke(context, null, obj);

            Thread.Sleep(10000);
            ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:BeginProcessRequestTest] strMensajeDeError=" + strMensajeDeError);
            return objResult;
        }

        private void callbackCrearCompetidor(IAsyncResult ar)
        {
            try
            {
                this.EndProcessRequest(ar);
                //   objTareaARealizar.finalizar();
                objTareaARealizar.actualizarEstado("Tarea terminada", "END_VISIBLE");
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:callbackCrearCompetidor] Liberando UNICA INSTANCIA...");
            }
            catch (CompetidorException ex)
            {
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:callbackCrearCompetidor] Excepcion finalizando tarea: " + ex.Message);
            }
        }

    
        public void EndProcessRequest(IAsyncResult ar)
        {
            try
            {
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:EndProcessRequest] EndProcess llamado correctamente ");
                this.del.EndInvoke(ar);
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ControlCompetidorCrearCompetidorAsyncHandler:EndProcessRequest] Excepcion en EndProcess = " + ex.Message);
                throw ex;
            }
        }

        public bool IsReusable { get { return true; } }
    }


    public class ControlCompetidorAnalizarCompetidorAsyncHandler : System.Web.IHttpAsyncHandler
    {
        public static string strMensajeDeError;

        TareaPendiente objTareaARealizar;
        private AsyncTaskDelegate del;
        private AsyncTaskDelegate delTest;
        protected delegate void AsyncTaskDelegate(HttpContext context);
        List<ItemValue> lstCompetidoresAProcesar;


        public ControlCompetidorAnalizarCompetidorAsyncHandler()
        {

        }

        public void ProcessRequest(HttpContext context)
        {
            string strNickUsuario = "";
            try
            {

                 Parametros objParametro = new Parametros();
                 DBMethods objConnection = new DBMethods();
                 List<String> lstStrPathDeArchivos = new List<String>();
                 List<Competidor> lstCompetidoresProcesados = new List<Competidor>();
           
                 if(ControlSesion.session("checkBoxProcesarProductos") == "TRUE")
                 {
                    objParametro.Productos = true;
                 }
                 if(ControlSesion.session("checkBoxProcesarCalificaciones") == "TRUE")
                 {                
                    objParametro.Calificaciones = true;
                 }

                if (Convert.ToInt32(ControlSesion.session("listboxCompetidoresAProcesar.Items.Count")) == 0)
                {
                     ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Debe haber al menos un competidor en la lista de procesamiento");
                     objTareaARealizar.actualizarEstado("Debe haber al menos un competidor en la lista de procesamiento", "ERROR");
                     Thread.Sleep(60000);                        
                     return;                   
                }

                if (objParametro.Productos || objParametro.Calificaciones)
                {
                    try
                    {

                        foreach (ItemValue objCompetidorItemValue in lstCompetidoresAProcesar)
                        {
                            objTareaARealizar.actualizarEstado("Procesando competidor " + objCompetidorItemValue.Text + "(" + objCompetidorItemValue.Value + ")", "En curso");
                            Competidor objCompetidor = new Competidor();
                            string strIdML = objConnection.getIdMLCompetidor(objCompetidorItemValue.Value).ToString();

                            objCompetidor = objConnection.getCompetidor(strIdML);
                            objTareaARealizar.actualizarEstado("Refrescando estadisticas de competidor " + objCompetidorItemValue.Text + "(" + objCompetidorItemValue.Value + ")", "En curso");
                            objCompetidor.refrescarEstadisticas();



                            lstCompetidoresProcesados.Add(objCompetidor);

                            Reporte.arrLstProductosAll = null;
                            Reporte.arrLstProductosNuevos = null;
                            Reporte.arrLstProductosNoEstan = null;
                            Reporte.arrLstProductosCambios = null;
                            Reporte.arrLstCalificacionesNuevas = null;
                            Reporte.lstCalificacion = new List<Calificacion>(); ;

                            if (objParametro.Productos)
                            {
                                #region Diferenciar Productos

                                try
                                {
                                    objTareaARealizar.actualizarEstado("Diferenciando productos actuales vs antiguos, de competidor " + objCompetidorItemValue.Text + "(" + objCompetidorItemValue.Value + ")", "En curso");
                                    Reporte.arrLstProductosAll = ControlCompetidorBO.ProcesarConsultaProductos(objCompetidor, this.objTareaARealizar);

                                    if (Reporte.arrLstProductosAll.Count > 0)
                                    {
                                        Reporte.arrLstProductosNuevos = ControlCompetidorBO.BuscarProductosNuevos(Reporte.arrLstProductosAll, objCompetidorItemValue.Value, this.objTareaARealizar);
                                        Reporte.arrLstProductosCambios = ControlCompetidorBO.BuscarProductosConCambios(Reporte.arrLstProductosAll, this.objTareaARealizar);
                                        Reporte.arrLstProductosNoEstan = ControlCompetidorBO.BuscarProductosNoEstan(Reporte.arrLstProductosAll, this.objTareaARealizar);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Error obteniendo productos: " + ex.Message);
                                    throw ex;
                                }

                                #endregion

                            }
                            if (objParametro.Calificaciones)
                            {
                                #region Diferenciar Calificaciones
                                try
                                {
                                    objTareaARealizar.actualizarEstado("Procesando calificaciones nuevas vs antiguas, de competidor " + objCompetidorItemValue.Text + "(" + objCompetidorItemValue.Value + ")", "En curso");
                                    Reporte.arrLstCalificacionesNuevas = ControlCompetidorBO.ProcesarConsultaCalificaciones(objCompetidor, null, null);

                                    for (int i = 0; i < Reporte.arrLstCalificacionesNuevas.Count; i++)
                                    {
                                        Calificacion objCalificacion = null;
                                        objCalificacion = (Calificacion)Reporte.arrLstCalificacionesNuevas[i];
                                        objConnection.crearCalificacion(objCalificacion, objCompetidorItemValue.Value);
                                    }

                                    Reporte.lstCalificacion = objConnection.getListaCalificacionesFK(objCompetidorItemValue.Value);

                                }
                                catch (Exception ex)
                                {
                                    ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Error obteniendo Calificaciones: " + ex.Message);
                                    throw ex;
                                }
                                #endregion
                            }

                            try
                            {
                                objTareaARealizar.actualizarEstado("Preparando reporte diferencial de competidor " + objCompetidorItemValue.Text + "(" + objCompetidorItemValue.Value + ")", "En curso");
                                string[] strArrName = objCompetidorItemValue.Text.Split(new char[] { ' ' });
                                /// Version 2.0.4.0
                                #region Validar nombre de archivo de reporte - Caracteres que puedan causar error.
                                try
                                {
                                    strArrName[0] = ControlReporte.validadorDeNombreDeArchivos(strArrName[0]);
                                }
                                catch (Exception ex)
                                {
                                    ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] WARNING: El archivo ReporteDiferencial_" + strArrName[0] + ".xls produjo un error al validarlo: " + ex.Message);
                                } 
                                #endregion

                                #region Borrar el archivo anterior de reporte diferencial para el usuario en cuestion
                                try
                                {
                                    File.Delete(ControlSesion.session("MapPath_Competidores") + "\\" + strIdML + "\\ReporteDiferencial_" + strArrName[0] + ".xls");
                                }
                                catch (Exception ee)
                                {
                                    ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] WARNING: No se pudo borrar el archivo " + ControlSesion.session("MapPath_Competidores") + "\\" + strIdML + "\\ReporteDiferencial_" + strArrName[0] + ".xls . Se procede con la operacion. (" + ee.Message + ")");
                                } 
                                #endregion

                                System.IO.StreamWriter file = new System.IO.StreamWriter(ControlSesion.session("MapPath_Competidores") + "\\" + strIdML + "\\ReporteDiferencial_" + strArrName[0] + ".xls");


                                strNickUsuario = strArrName[0];

                                ControlReporte.exportarXLSReporteDiferencial(strArrName[0], objCompetidorItemValue.Value,
                                                                                Reporte.arrLstProductosNuevos, Reporte.arrLstProductosNoEstan,
                                                                                Reporte.arrLstProductosCambios, Reporte.arrLstProductosAll, Reporte.arrLstCalificacionesNuevas, Reporte.lstCalificacion,
                                                                                objParametro).WriteTo(file.BaseStream);

                                lstStrPathDeArchivos.Add("www.mymimportacionesweb.com.ar\\Competidores\\" + strIdML + "\\ReporteDiferencial_" + strArrName[0] + ".xls");
                                file.Close();

                                //Response.End();	

                            }
                            catch (Exception ex)
                            {
                                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Error armando el reporte: " + ex.Message);
                                throw ex;
                            }

                        }

                        string[] filePaths = Directory.GetFiles(ControlSesion.session("MapPath_Competidores"));
                        foreach (string filePath in filePaths)
                            File.Delete(filePath);


                        #region Armado Reporte HTM


                        string strPathHTMFile = "Reporte.htm";
                        System.IO.StreamWriter objHTMFile = new System.IO.StreamWriter(ControlSesion.session("MapPath_Competidores") + "\\" + strPathHTMFile);
                        ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] FilePath del reporte: " + ControlSesion.session("MapPath_Competidores") + "\\" + strPathHTMFile);


                        objTareaARealizar.actualizarEstado("Armando reporte en " + ControlSesion.session("MapPath_Competidores") + "\\" + strPathHTMFile, "En curso");


                        ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Archivos XLS procesados: " + lstStrPathDeArchivos.Count);



                        string sHeader = "<table width=1024px " + ControlReporte.estiloRojo() + " ><tr><td><table width=100%><tr align=center><td colspan=2 align=center><h1>Novedades del competidor COMPETENCIA</h1></td></tr>" +
                                "<tr><h1></h1></tr>" +
                                "<tr><td colspan=2 align=center><b> Programa Competidores - MYM IMPORTACIONES </b></td></tr>" +
                                "<tr><td>Archivos EXCEL de reportes:<td/><tr/>";


                        objHTMFile.Write(sHeader);



                        foreach (String strFile in lstStrPathDeArchivos)
                        {
                            ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Agregando: <tr><td>" + strFile + "<br/></td></tr>");
                            objHTMFile.Write("<tr><td><a href=\"http://" + strFile + "\">" + strFile + "<a/><br/></td></tr>");
                        }


                        int intEstilo = 0;
                        foreach (Competidor objCompetidorProcesado in lstCompetidoresProcesados)
                        {
                            if (intEstilo < 3)
                            {
                                intEstilo++;
                            }
                            else
                            {
                                intEstilo = 0;
                            }

                            objHTMFile.Write(ControlReporte.procesarReporteTotalizadores(objCompetidorProcesado, intEstilo));
                        }


                        objHTMFile.Write("</table>");
                        objHTMFile.Close();

                        #endregion

                    }

                    catch (Exception ee)
                    {
                        ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Excepcion General armando reporte diferencial: " + ee.Message);
                        objTareaARealizar.actualizarEstado("Excepcion General armando reporte diferencial: " + ee.Message, "ERROR");
                        Thread.Sleep(60000);
                        return;
                    }

                }
                else
                {
                    objTareaARealizar.actualizarEstado("Debe elegir el CheckBox Producto y/o Calificaciones", "ERROR");
                    Thread.Sleep(60000);
                }
            }
            catch (CompetidorException compEx)
            {
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] EXCEPCION de analisis de Competidores: " + compEx.Message);
                objTareaARealizar.actualizarEstado(compEx.Message, "ERROR");
                Thread.Sleep(60000);
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequest] Excepcion Procesando Tarea de analisis de Competidores: " + ex.Message);
            }
        }
                  
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object obj)
        {
            this.del = new AsyncTaskDelegate(ProcessRequest);
            lstCompetidoresAProcesar = new List<ItemValue>();
            lstCompetidoresAProcesar = (List<ItemValue>)obj;
            AsyncCallback objCallBack = new AsyncCallback(callbackAnalizandoCompetidor);
            objTareaARealizar = new TareaPendiente();
            objTareaARealizar.crearTarea(ControlSesion.session(ControlSesion.UsuarioLogin), "CompetidoresAnalisis", "Analizando competidor  [" + System.DateTime.Now.ToString() + "]");
            return del.BeginInvoke(context, objCallBack, obj);


        }



        public void ProcessRequestTest(HttpContext context)
        {
            try
            {
                strMensajeDeError = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:ProcessRequestTest] Soy " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
            }
            catch (Exception ex)
            {
                strMensajeDeError = " Excepcion = " + ex.Message;
            }
        }

        public IAsyncResult BeginProcessRequestTest(HttpContext context, AsyncCallback cb, object obj)
        {
            this.delTest = new AsyncTaskDelegate(ProcessRequestTest);


            IAsyncResult objResult = delTest.BeginInvoke(context, null, obj);

            Thread.Sleep(10000);
            ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:BeginProcessRequestTest] strMensajeDeError=" + strMensajeDeError);
            return objResult;
        }

        private void callbackAnalizandoCompetidor(IAsyncResult ar)
        {
            try
            {
                this.EndProcessRequest(ar);
                //   objTareaARealizar.finalizar();
                objTareaARealizar.actualizarEstado("Tarea terminada", "END_VISIBLE");
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:callbackCrearCompetidor] Liberando UNICA INSTANCIA...");
            }
            catch (CompetidorException ex)
            {
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:callbackCrearCompetidor] Excepcion finalizando tarea: " + ex.Message);
            }
        }


        public void EndProcessRequest(IAsyncResult ar)
        {
            try
            {
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:EndProcessRequest] EndProcess llamado correctamente ");
                this.del.EndInvoke(ar);
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[ControlCompetidorAnalizarCompetidorAsyncHandler:EndProcessRequest] Excepcion en EndProcess = " + ex.Message);
                throw ex;
            }
        }

        public bool IsReusable { get { return true; } }
    }
}